package com.kartoshka.painters
{
	import flash.geom.Rectangle;
	import flash.geom.Matrix;
	import flash.display.BitmapData;
	import flash.display.Graphics;

	public class BackgroundBitmapPainter extends NullPainter 
	{

		public static const NO_SCALE : String = "noScale";
		public static const SCALE_X : String = "scaleX";
		public static const SCALE_Y : String = "scaleY";
		public static const SCALE_BOTH : String = "scaleBoth";

		public static const NO_REPEAT : String = "noRepeat";
		public static const REPEAT_X : String = "repeatX";
		public static const REPEAT_Y : String = "repeatY";
		public static const REPEAT_BOTH : String = "repeatBoth";

		protected var _image : BitmapData;
		protected var _scaleMode : String;
		protected var _repeat : Boolean;
		protected var _scale9Grid : Rectangle;
		protected var _smooth : Boolean;

		public function BackgroundBitmapPainter( image : BitmapData = null, scaleMode : String = "noScale", repeat : Boolean = true )
		{
			_image = image;
			_scaleMode = scaleMode;
			_repeat = repeat;
		}

		override public function draw( graphics : Graphics, width : Number, height : Number ) : void
		{
			var scaleMatrix : Matrix;
			if ( _scaleMode != NO_SCALE )
			{
				scaleMatrix = new Matrix( );
				switch ( _scaleMode )
				{
					case SCALE_X:
						scaleMatrix.scale( width / _image.width, 1 );
						break;
					case SCALE_Y:
						scaleMatrix.scale( 1, height / _image .height );
						break;
					case SCALE_BOTH:
						scaleMatrix.scale( width / _image.width, height / _image .height );
						break;
				}
			}
			if ( ! _scale9Grid )
			{
				graphics.beginBitmapFill( _image, scaleMatrix, _repeat, _smooth );
				graphics.drawRect( 0, 0, width, height );
			}
			else
			{
				//Due to some weird bug we can't dispose bitmap after each iteration

				var bd : BitmapData;
				var ma : Matrix = new Matrix( );
				var adjustedScale9Grid : Rectangle = _scale9Grid.clone( );
				adjustedScale9Grid.width = width - _scale9Grid.left - ( _image.width - _scale9Grid.right );
				adjustedScale9Grid.height = height - _scale9Grid.top - ( _image.height - _scale9Grid.bottom );
				
				//TL
				bd = new BitmapData( _scale9Grid.left, _scale9Grid.top, true, 0x00000000 );
				ma.identity( );
				ma.tx = 0;
				ma.ty = 0;
				bd.draw( _image, ma, null, null, null, false );
				ma.tx = 0;
				ma.ty = 0;
				graphics.beginBitmapFill( bd, ma, false, _smooth );
				graphics.drawRect( 0, 0, adjustedScale9Grid.left, adjustedScale9Grid.top );
			
				//T
				bd = new BitmapData( _scale9Grid.width, _scale9Grid.top, true, 0x00000000 );
				ma.identity( );
				ma.tx = - _scale9Grid.left;
				ma.ty = 0;
				bd.draw( _image, ma, null, null, null, false );
				if ( _scaleMode == SCALE_X || _scaleMode == SCALE_BOTH ) ma.scale( adjustedScale9Grid.width / _scale9Grid.width, 1 );
				ma.tx = adjustedScale9Grid.left;
				ma.ty = 0;
				graphics.beginBitmapFill( bd, ma, true, _smooth );
				graphics.drawRect( adjustedScale9Grid.left, 0, adjustedScale9Grid.width, adjustedScale9Grid.top );
			
				//TR
				bd = new BitmapData( _image.width - _scale9Grid.right, _scale9Grid.top, true, 0x00000000 );
				ma.identity( );
				ma.tx = - _scale9Grid.right;
				ma.ty = 0;
				bd.draw( _image, ma, null, null, null, false );
				ma.tx = adjustedScale9Grid.right;
				ma.ty = 0;
				graphics.beginBitmapFill( bd, ma, false, _smooth );
				graphics.drawRect( adjustedScale9Grid.right, 0, width - adjustedScale9Grid.right, adjustedScale9Grid.top );
			
				//R
				bd = new BitmapData( _image.width - _scale9Grid.right, _scale9Grid.height, true, 0x00000000 );
				ma.identity( );
				ma.tx = - _scale9Grid.right;
				ma.ty = - _scale9Grid.top;
				bd.draw( _image, ma, null, null, null, false );
				if ( _scaleMode == SCALE_Y || _scaleMode == SCALE_BOTH ) ma.scale( 1, adjustedScale9Grid.height / _scale9Grid.height );
				ma.tx = adjustedScale9Grid.right;
				ma.ty = adjustedScale9Grid.top;
				graphics.beginBitmapFill( bd, ma, true, _smooth );
				graphics.drawRect( adjustedScale9Grid.right, adjustedScale9Grid.top, width - adjustedScale9Grid.right, adjustedScale9Grid.height );
			
				//BR
				bd = new BitmapData( _image.width - _scale9Grid.right, _image.height - _scale9Grid.bottom, true, 0x00000000 );
				ma.identity( );
				ma.tx = - _scale9Grid.right;
				ma.ty = - _scale9Grid.bottom;
				bd.draw( _image, ma, null, null, null, false );
				ma.tx = adjustedScale9Grid.right;
				ma.ty = adjustedScale9Grid.bottom;
				graphics.beginBitmapFill( bd, ma, false, _smooth );
				graphics.drawRect( adjustedScale9Grid.right, adjustedScale9Grid.bottom, width - adjustedScale9Grid.right, height - adjustedScale9Grid.bottom );
			
				//B
				bd = new BitmapData( _scale9Grid.width, _image.height - _scale9Grid.bottom, true, 0x00000000 );
				ma.identity( );
				ma.tx = - _scale9Grid.left;
				ma.ty = - _scale9Grid.bottom;
				bd.draw( _image, ma, null, null, null, false );
				if ( _scaleMode == SCALE_X || _scaleMode == SCALE_BOTH ) ma.scale( adjustedScale9Grid.width / _scale9Grid.width, 1 );
				ma.tx = adjustedScale9Grid.left;
				ma.ty = adjustedScale9Grid.bottom;
				graphics.beginBitmapFill( bd, ma, true, _smooth );
				graphics.drawRect( adjustedScale9Grid.left, adjustedScale9Grid.bottom, adjustedScale9Grid.width, height - adjustedScale9Grid.bottom );
			
				//BL
				bd = new BitmapData( _scale9Grid.left, _image.height - _scale9Grid.bottom, true, 0x00000000 );
				ma.identity( );
				ma.tx = 0;
				ma.ty = - _scale9Grid.bottom;
				bd.draw( _image, ma, null, null, null, false );
				ma.tx = 0;
				ma.ty = adjustedScale9Grid.bottom;
				graphics.beginBitmapFill( bd, ma, false, _smooth );
				graphics.drawRect( 0, adjustedScale9Grid.bottom, adjustedScale9Grid.left, height - adjustedScale9Grid.bottom );
			
				//L
				bd = new BitmapData( _scale9Grid.left, _scale9Grid.height, true, 0x00000000 );
				ma.identity( );
				ma.tx = 0;
				ma.ty = - _scale9Grid.top;
				bd.draw( _image, ma, null, null, null, false );
				if ( _scaleMode == SCALE_Y || _scaleMode == SCALE_BOTH ) ma.scale( 1, adjustedScale9Grid.height / _scale9Grid.height );
				ma.tx = 0;
				ma.ty = adjustedScale9Grid.top;
				graphics.beginBitmapFill( bd, ma, true, _smooth );
				graphics.drawRect( 0, adjustedScale9Grid.top, adjustedScale9Grid.left, adjustedScale9Grid.height );
			
				//C
				bd = new BitmapData( _scale9Grid.width, _scale9Grid.height, true, 0x00000000 );
				ma.identity( );
				ma.tx = - _scale9Grid.left;
				ma.ty = - _scale9Grid.top;
				bd.draw( _image, ma, null, null, null, false );
				if ( _scaleMode == SCALE_BOTH ) ma.scale( adjustedScale9Grid.width / _scale9Grid.width, adjustedScale9Grid.height / _scale9Grid.height );
				else if ( _scaleMode == SCALE_Y ) ma.scale( 1, adjustedScale9Grid.height / _scale9Grid.height );
				else if ( _scaleMode == SCALE_X ) ma.scale( adjustedScale9Grid.width / _scale9Grid.width, 1 );
				ma.tx = adjustedScale9Grid.left;
				ma.ty = adjustedScale9Grid.top;
				graphics.beginBitmapFill( bd, ma, true, _smooth );
				graphics.drawRect( adjustedScale9Grid.left, adjustedScale9Grid.top, adjustedScale9Grid.width, adjustedScale9Grid.height );
			}
			graphics.endFill( );
		}

		
		public function set scaleMode( value : String ) : void
		{
			_scaleMode = value;
		}

		public function get scaleMode( ) : String
		{
			return _scaleMode;
		}

		
		public function set repeat( value : Boolean ) : void
		{
			_repeat = value;
		}

		public function get repeat( ) : Boolean
		{
			return _repeat;
		}

		public function get image() : BitmapData
		{
			return _image;
		}

		public function set image( value : BitmapData ) : void
		{
			_image = value;
		}

		public function get scale9Grid() : Rectangle
		{
			return _scale9Grid;
		}

		public function set scale9Grid( value : Rectangle ) : void
		{
			_scale9Grid = value;
		}

		public function get smooth() : Boolean
		{
			return _smooth;
		}

		public function set smooth(value : Boolean) : void
		{
			_smooth = value;
		}
	}
}